<!-- 穿梭框 -->
<template>
    <div class="si-transfer">
        <div class="transfer-panel">
            <div class="transfer-panel-header">
                <div class="transfer-panel-header-label">
                    {{ titles[0] || '' }}
                    <span>{{ leftMoveList.length }} / {{ dataTotal }}</span>
                </div>
            </div>
            <div class="transfer-panel-body">
                <el-input
                    v-model="leftKeyword"
                    class="transfer-panel-filter"
                    placeholder="请输入搜索内容"
                    prefix-icon="icon-search"
                    @change="onSearchLeftData"
                />
                <el-scrollbar v-if="data.length > 0" v-loading="dataLoading" class="transfer-panel-list-scrollbar">
                    <el-checkbox-group :modelValue="[...leftMoveList.map(item => item[props.key]), ...modelValue.map(item => item[props.key])]" class="transfer-panel-list">
                        <template v-for="(item, index) in data" :key="index">
                            <el-checkbox
                                :label="item[props.key]"
                                :disabled="modelValue.some(n => n[props.key] === item[props.key])"
                                class="transfer-panel-item"
                                @click.stop.prevent="onMoveChange(leftMoveList, item, modelValue.some(n => n[props.key] === item[props.key]))"
                            >
                                {{ item[props.label] }}
                            </el-checkbox>
                        </template>
                    </el-checkbox-group>
                </el-scrollbar>
                <div v-else class="transfer-panel-empty">无数据</div>
            </div>
            <div v-if="showLeftFooter" class="transfer-panel-footer">
                <div class="transfer-footer">
                    <slot name="left-footer"></slot>
                </div>
            </div>
        </div>

        <div class="transfer-buttons">
            <el-button type="primary" icon="icon-arrow-left" :disabled="rightMoveList.length === 0" :class="{ 'no-txt-btn': buttonTexts[0] === undefined }" @click="onMoveData('left')">
                {{ buttonTexts[0] || '' }}
            </el-button>
            <el-button type="primary" icon="icon-arrow-right" :disabled="leftMoveList.length === 0" :class="{ 'no-txt-btn': buttonTexts[1] === undefined }" @click="onMoveData('right')">
                {{ buttonTexts[1] || '' }}
            </el-button>
        </div>

        <div class="transfer-panel">
            <div class="transfer-panel-header">
                <div class="transfer-panel-header-label">
                    {{ titles[1] || '' }}
                    <span>{{ rightMoveList.length }} / {{ modelValue.length }}</span>
                </div>
            </div>
            <div class="transfer-panel-body">
                <el-input
                    v-model="rightKeyword"
                    class="transfer-panel-filter"
                    placeholder="请输入搜索内容"
                    prefix-icon="icon-search"
                />
                <el-scrollbar v-if="modelValueFilter.length > 0" class="transfer-panel-list-scrollbar">
                    <el-checkbox-group :modelValue="rightMoveList.map(item => item[props.key])" class="transfer-panel-list">
                        <template v-for="(item, index) in modelValueFilter" :key="index">
                            <el-checkbox
                                :label="item[props.key]"
                                class="transfer-panel-item"
                                @click.stop.prevent="onMoveChange(rightMoveList, item)"
                            >
                                {{ item[props.label] }}
                            </el-checkbox>
                        </template>
                    </el-checkbox-group>
                </el-scrollbar>
                <div v-else class="transfer-panel-empty">无数据</div>
            </div>
            <div v-if="showRightFooter" class="transfer-panel-footer">
                <div class="transfer-footer">
                    <slot name="right-footer"></slot>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import { defineComponent, toRefs, useSlots, ref, computed } from 'vue'
import { deepClone } from '@/libs/tools'
export default defineComponent({
    name: 'SiTransfer',
    props: {
        // 选中项的数据([{ label, key }])
        modelValue: {
            type: Array,
            default: () => ([])
        },
        // 数据源([{ label, key }])
        data: {
            type: Array,
            default: () => ([])
        },
        // 数据源总数
        dataTotal: {
            type: Number,
            default: 0
        },
        // 数据源加载状态
        dataLoading: {
            type: Boolean,
            default: false
        },
        // 数据源搜索内容
        dataKeyword: {
            type: String,
            default: ''
        },
        // 自定义列表标题(['列表1'， '列表2'])
        titles: {
            type: Array,
            default: () => (['列表1', '列表2'])
        },
        // 自定义列表标题(['按钮1'， '按钮2'])
        buttonTexts: {
            type: Array,
            default: () => ([])
        },
        // 列表顶部勾选状态文案
        format: {
            type: Object,
            default: () => ({
                noChecked: '',
                hasChecked: ''
            })
        },
        // 数据源的字段别名
        props: {
            type: Object,
            default: () => ({
                key: 'key',
                label: 'label'
            })
        }
    },
    emits: [
        'update:modelValue',
        'update:dataKeyword',
        'data-search', // 搜索数据源，回调参数(搜索内容)
        'change' // 右侧列表元素变化时触发，回调参数(当前值、数据移动的方向（'left' / 'right'）、发生移动的数据 key 数组)
    ],
    setup(prop, { emit }) {
        const { modelValue, data, dataTotal, dataLoading, dataKeyword, titles, buttonTexts, format, props } = toRefs(prop)
        
        const slots = useSlots()

        const leftMoveList = ref([])

        const rightMoveList = ref([])
        const rightKeyword = ref('')

        const leftKeyword = computed({
            get: () => dataKeyword.value,
            set: val => emit('update:dataKeyword', val)
        })
        const modelValueFilter = computed(() => modelValue.value.filter(item => item[props.value.label].includes(rightKeyword.value)))
        const showLeftFooter = computed(() => slots['left-footer'] !== undefined)
        const showRightFooter = computed(() => slots['right-footer'] !== undefined)

        const onSearchLeftData = () => {
            emit('data-search', leftKeyword.value)
        }

        const onMoveChange = (list, data, disabled = false) => {
            if (disabled) return
            const index = list.findIndex(item => item[props.value.key] === data[props.value.key])
            if (index === -1) list.push(data)
            else list.splice(index, 1)
        }

        const onMoveData = direction => {
            if (direction === 'right') {
                const list = [...modelValue.value, ...deepClone(leftMoveList.value)]
                leftMoveList.value = []
                emit('update:modelValue', list)
                emit('change', direction, list)
            }
            else if (direction === 'left') {
                const list = modelValue.value.filter(item => !rightMoveList.value.some(n => n[props.value.key] === item[props.value.key]))
                rightMoveList.value = []
                emit('update:modelValue', list)
                emit('change', direction, list)
            }
        }

        return {
            modelValue,
            data,
            dataTotal,
            dataLoading,
            titles,
            buttonTexts,
            format,
            props,

            leftMoveList,
            leftKeyword,
            rightMoveList,
            rightKeyword,

            modelValueFilter,

            showLeftFooter,
            showRightFooter,

            onSearchLeftData,
            onMoveChange,
            onMoveData
        }
    }
})
</script>

<style lang="less" scoped>
@import './si-transfer.less';
</style>